
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.Data;
using System.Text.RegularExpressions;
using System.Xml;
using Swaf;
using Swaf.BizObj;
using Swaf.DataAccess;

namespace Swaf.DataAccess
{
    /// <summary>
    /// This formatter will consume an ADO.Net DataReader with 1 or more result sets within
    /// in and will map those result sets to business objects using an Xml catalog "Map".  The output
    /// will always be an IList object if there are more than one entries in the map.  Otherwise, it will
    /// return either an IBizObj or an IBizObjList depending on the definition within the map.
    /// </summary>

    public interface IGroupFormatter
    {
        object format(AdoNetDataResponse response);
        bool IsMerge { get;}
    }

    public class AdoNetBizObjGroupFormatter : IDataFormatter
    {
        protected AdoNetDataResponse m_resp;
        protected IApplication m_app;
        protected string m_groupName = "";
        BizObjGroupContainerNode m_groupInfo = null;
        public AdoNetBizObjGroupFormatter(Match mr, object[] extraInfo)
        {
            if (extraInfo != null && extraInfo.Length > 0 && extraInfo[0] is AdoNetDataResponse)
            {
                m_resp = (AdoNetDataResponse)extraInfo[0];
                m_app = Application.currentApp;

                m_groupName = mr.Groups[1].Value;
                m_groupInfo = (BizObjGroupContainerNode)Application.currentApp.appData.get("GroupFormats." + m_groupName);
            }
        }
        #region IDataFormatter Members

        public object format()
        {
            IDataReader reader = m_resp.Reader;
            IList results = new ArrayList();
            object thisResult = null;

            for (int idx = 0; idx < m_groupInfo.groups.Count; idx++)
            {
                IGroupFormatter formatter = (IGroupFormatter)m_groupInfo.groups[idx];
                //If this formatter is a merge formatter store the previous results in the
                // input parms to make them available to it.
                if (formatter.IsMerge)
                {
                    for (int resIdx = 0; resIdx < results.Count; resIdx++)
                    {
                        object res = results[resIdx];
                        try
                        {
                            m_resp.putPassedItem("_result" + resIdx.ToString(), res);
                        }
                        catch (Exception e)
                        {
                            // Unable to save the result to merge into, so have to error
                            throw new DataFormatException("Unable to save _result in response object, group formatter can not complete", e);
                        }
                    }
                }
                thisResult = formatter.format(m_resp);
                //Only add non-null results.
                if (thisResult != null)
                    addResult(results, thisResult);

                if (!reader.NextResult())
                    break;
            }
            //If there is only 1 result return it, otherwise return the array list.
            if (results.Count == 1)
                return results[0];
            else
                return results;
        }
        private void addResult(IList results, object result)
        {
            bool addThis = true;
            foreach (object entry in results)
            {
                if (entry.Equals(result))
                {
                    addThis = false;
                    break;
                }
            }
            if (addThis)
                results.Add(result);
        }
        #endregion
    }

    public class BizObjListGroupFormatter : IGroupFormatter
    {
        protected string m_defaultFormatter = "";
        protected bool m_isMerge = false;
        public BizObjListGroupFormatter(XmlElement req)
        {
            m_defaultFormatter = req.GetAttribute("format");
            m_isMerge = m_defaultFormatter.StartsWith("merge") || m_defaultFormatter.StartsWith("match merge");

        }
        public object format(AdoNetDataResponse response)
        {
            IDataFormatter f = (IDataFormatter)Application.currentApp.factories["AdoNetFormatters"].createFromPattern(m_defaultFormatter, response);
            return f.format();
        }
        public bool IsMerge
        {
            get { return m_isMerge; }
        }
    }
}
